home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
038a
/
edit_qb.zip
/
EDIT.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-05-23
|
22KB
|
544 lines
;«RM92»«TS8,16,24,32,40,48»
; updated 5/21/91
DOSSEG
.MODEL MEDIUM, BASIC
.DATA
EXTRN B$TEMPDATA:WORD ;inside FDATA, 128 byte buffer
EXTRN B$STRINGLEN:WORD ;inside FDATA, empty string descriptor
EXTRN B$STRINGOFF:WORD ;inside FDATA
.CODE
EXTRN B$ASSN:FAR ;This allows QBASIC to manipulate fixed length string
EXTRN B$STDL:FAR ;This creates null strings
; Please do not remove
Copyright DB 13,10,'Copyright Copr. (C) 1991 Sidney J. Kelly',13,10
Copyright1 DB 'All Rights Reserved',13,10,26
COPY_STRING_BUFFER macro
;;Copies user input string to a buffer (FDATA.ASM)
;;Does not test length of string!
;;Uses SI,DI,ES,AX,CX,BX
;;Assumes BX = address of string descriptor
;; CX = length of string
;; DS = segment of string
;; ES = DGROUP
;; Direction Flag clear, CLD
;;Trashes AX, SI, DI and CX
Mov SI,[BX+2] ;; put offset of string in SI
Mov DI,OFFSET B$TEMPDATA ;; put address of buffer in DI
;;Rep MOVSB ;; copy the string to buffer
;;The following is faster than a MOVSB routine
Shr CX,1 ;; convert bytes to word
Rep MOVSW ;; move DS:SI to ES:DI
ADC CX,CX ;; CX=1 if bytes were odd, 0 if even
Rep MOVSB ;; copy the odd byte if there was one
endm
ASCII_Space EQU 32
EVEN
;memory rather than stack used allow deep nesting of routine
;prevents use under OS/2 or protected mode
Right_Edge dw 0 ; right edge of Buffer
Max_Cursor dw 0 ; dimension of max cursor
Min_Cursor dw 0 ; dimension of min cursor
Orig_Cursor dw 0 ; original cursor shape
Exit_Key dw 0 ; key hit to exit routine
Old_BP dw 0 ; temp storage for BP, to correct
; for bug in early PC video bios
; that changes BP
Max_Len db 0 ; max length of Result$
Curr_Page db 0 ; current video page
Insert_State db 0 ; -1 = insert on, 0 = insert off
Start_Row db 0 ; Starting Row
Start_Col db 0 ; Starting Column
Curr_Row db 0 ; (never really used)
Curr_Col db 0 ; Current column location
Max_Right db 0 ; rightmost column
Curr_V_Mode db 0 ; fix for rom BIOS error
; in AST 386/AMI 386 BIOS
;=======================================================================
; DECLARE FUNCTION EDITOR$ (BYVAL ROW%, BYVAL COL%, BYVAL LENGTH%, _
; BYVAL ATTR%, INPUT$, FILTER$, EXITKEY%)
; Result$ = EDITOR$ (ROW%, COL%, LENGTH%, ATTR%, FILTER$, EXITKEY%)
; Compatible input editor, allowed keystrokes limited by Filter$.
; Extended keys not recognized, primarily for alpha-numeric input only
; Allows editing using any video page supported by the video system
;
; Editing keys recognized;
; Home: move cursor to beginning of window
; Insert; toggle insert mode, default mode is insert on
; End; move cursor to end of window
; Del: moves string left, deletes character under cursor
; Backspace: moves string left, deletes character to left of cursor
; Currently ESC, ENTER, TAB, and SHIFT-TAB will end the routine
;
; Input:
; Row: Row on screen 1 to 50, no range check is performed
; Col: Starting Column 1 to 80, no range check is performed
; Length: Length of editing window, no range check performed
; If extends past right border, then wraps to lower line.
; Attr: Color attribute for window (back * 16 + foreground color)
; Input$: allows programmer to feed routine an existing string
; for editing. The Input$ is not changed, only Result$ is.
; Filter$: the input filter string, if LEN(Filter$) = 0 then
; every key is o.k.
; Exitkey%: the scan code of the key used to exit the routine
; currently ESC, ENTER, TAB, and SHIFT-TAB recognized
;=======================================================================
EVEN
EDITOR PROC FAR BASIC USES SI DI, ROW:WORD, COL:WORD, \
LENGTHH:WORD, ATTR:WORD, INPUT:WORD, FILTER:WORD, EXITKEY:WORD
Assume DS:@data
Setup:
Mov Old_BP,BP ; store it because bios may change BP
; and we need it to access stack correctly
Mov AX,@data ; this is a pointer to DGROUP
Mov ES,AX ; move near data seg to ES
Assume ES:@data ; tell assembler
CLD ; clear direction flag for safety
Mov AX,2020h ; load spaces in AX
Mov CX,44 ; count 44 words, 88 bytes to be safe
Mov DI,OFFSET B$TEMPDATA ; load offset of buffer in DI
Rep STOSW ; fill buffer (ES:DI) with spaces
Mov AL,0FFh ; make AL = -1 to record using insert mode
Mov Insert_State,AL
Mov AX,LENGTHH ; get length of output string into AX (BYVAL)
Or AX,AX ; make sure not 0
JNZ Setup1 ; not 0, so jump ahead
Mov AX,1 ; make AX = 1, so can read one character
Jmp Short Setup2 ; jump ahead
Setup1:
Cmp AL,80 ; make sure LENGTHH < than size of buffer
JBE Setup2 ; range o.k. so continue
Mov AL,80 ; else make it 80 character max
Setup2:
Mov Max_Len,AL ; store in CSEG
Mov BL,AL ; store temporarily in BL
Dec BL ; make length 0 biased
Mov AX,ROW ; get starting row into AX (BYVAL)
Dec AL ; make 0 bias
Mov Start_Row,AL ; store value
Mov Curr_Row,AL ; put cursor at beginning
Mov AX,COL ; get starting column into AX (BYVAL)
Dec AL ; make 0 bias
Mov Start_Col,AL ; store value
Mov Curr_Col,AL ; put cursor at beginning
Add AL,BL ; add Curr_Col+(Max_Len-1)
Mov Max_Right,AL ; store in Max_Right
Mov AX,OFFSET B$TEMPDATA ; load offset of buffer in AX
Add AL,BL ; add 0 biased length to buffer offset
Mov Right_Edge,AX ; store in memory for fast access
Get_Video_Info:
Mov AH,0Fh ; get current page number in BH
Int 10h
Mov Curr_Page,BH ; save current page number
Mov Curr_V_Mode,AL ; save current video mode
Cmp AL,7 ; mono mode?
JNE Try_Color ; nope, try color
Mov AH,3 ; get current default size
Int 10h
Mov Orig_Cursor,CX ; save current cursor shape
Mov CX,000Ch ; use mono sizing
Mov Max_Cursor,CX ; set max cursor size
Mov AH,1 ; to model insert mode
Int 10h
Mov CH,0Bh ; set min cursor size for mono
Mov Min_Cursor,CX ; save it
Jmp Short Other_Info ; skip over color sections
Try_Color:
Mov AH,3 ; BH must contain current page number
Int 10h ; returns current cursor in CX
Mov Orig_Cursor,CX ; save current cursor shape
Mov DX,CX ; copy value in DX too for temporary storage
Xor CH,CH ; clear top value so it is 0
Mov Max_Cursor,CX ; store maximum size in CSEG
Mov AH,1 ; AL contains current video mode
Int 10h ; set cursor to maximum size
Mov CL,DL ; get back temporary value from DX
Mov CH,DL
Dec CH ; reduce top scan value by one
Mov Min_Cursor,CX ; store in Min value
Other_Info:
Call Near Ptr Mov_Cursor ; move cursor where desired
Mov BP,Old_BP ; restore BP in case bios changed it
Mov AX,ATTR ; get attribute in AX (BYVAL)
Or AX,AX ; see if it is zero
JNZ @f
Mov AL,7 ; use default of White on Black
@@:
Mov BL,AL ; put display attribute in BL
; BH already contains current page
Mov AX,0920h ; get ready to print spaces
Mov CL,Max_Len ; write spaces on screen
Xor CH,CH ; print spaces using function 9
Int 10h ; as this allows us to set attributes
; but it does not move cursor
; so this is the only time we use it
Mov DL,CL ; store Max_Len in DL
Xor DH,DH ; clear DH
Mov BP,Old_BP ; restore BP in case bios changed it
Mov BX,INPUT ; get address of input string
Mov CX,[BX] ; get length in CX
JCXZ Clear_Keyb ; if LEN=0 then skip ahead
Cmp CX,DX ; is LEN > Max_Len
JBE @f ; it is less than or equal so jump ahead
Mov CX,DX ; make LEN of Imput$ = Max_Len
@@:
Mov DX,CX ; store LEN in DX, because CX will be trashed
COPY_STRING_BUFFER ; copy Input$ to buffer MACRO
Mov AL,Curr_Col ; get starting column
Add AL,DL ; add LEN to Start_Row
Mov BL,Max_Right ; get address of right side
Cmp AL,BL ; see if AL > Max_Right
JBE @f ; if less than or equal, skip ahead
Mov AL,BL ; limit cursor to right side of buffer
@@:
Mov Curr_Col,AL ; move cursor to end of string
Call Near Ptr Show_String ; show input string
EVEN
Clear_Keyb:
; make sure buffer is empty when we start
; there are faster ways, but this is the most compatible way
; faster way will be incompatible with Tandy machines
Mov AH,1 ; clear keyboard buffer
Int 16h
JZ Main ; no key waiting so quit
Xor AH,AH ; get key into AX
Int 16h
Jmp Short Clear_Keyb ; loop until buffer is empty
EVEN
Main: ; this is the main loop, most everything returns here
Xor AH,AH ; this will wait until a key is pressed
Int 16h ; use BIOS so CTRL-C, CTRL-BREAK wont
; kill program
Or AL,AL ; is it an extended key?
JZ Parse_Extended ; yes
Cmp AL,ASCII_Space ; below ASCII 32 (space character)
JB Parse_Control ; yes, treat as control key
Mov BP,Old_BP ; restore BP in case bios changed it
Mov BX,FILTER ; check if an allowed key
Mov CX,[BX] ; move length ito CX, if LEN(FILTER$) = 0
Jcxz Add_String ; then, by definition, got the right key
Mov DI,ES:[BX+2] ; move address of FILTER$ to DI
Repne Scasb ; search for match
JNE Err_Beep ; did we search entire string?, if yes Beep
Add_String:
Jmp Add_Char ; add AL to string buffer & display it
EVEN
Err_Beep:
Mov AX, 0E07h ; Write ASCII 7 character
Int 10h ; (bell) to console (BEEP)
; this makes the beep CPU speed independent
Jmp Short Clear_Keyb; clear KBD buffer to prevent excess keys
EVEN
Parse_Control: ; parse control keys
Mov Exit_Key,AX ; store exit key in CSEG buffer
Cmp AL,9 ; Is it a tab key?
JE Quit1 ; yes, so quit
Cmp AL,13 ; Is it a carriage return key?
JE Quit1 ; yes, so quit
Cmp AL,27 ; Is it an escape key?
JE Quit1 ; yes, so quit
Cmp AL,8 ; Is it backspace?
JNE Main ; not any of the above so reloop
; Send BackSpace ; else, send backspace
Mov AL,Curr_Col ; get current column
Cmp AL,Start_Col ; see > starting column
JA Back_S ; it is, so o.k.
Jmp Err_Beep ; else, at left margin can go no more
Back_S:
Dec AL ; reduce current column by one
Mov Curr_Col,AL ; store result
Call Near Ptr Mov_Buff_Left ; move buffer left
Call Near Ptr Show_String ; display changes
Jmp Main
EVEN
Quit1: ; lilly pad
Jmp Quit
EVEN
Parse_Extended: ; parse extended keys
Mov Exit_Key,AX ; store exit key in CSEG buffer
Cmp AH,15 ; is it shift-tab
JE Quit1 ; yes, so quit
Cmp AH,52h ; is it Insert
JNE @f ; nope, so jump ahead
Toggle_Insert: ; Toggle Insert mode
Mov AL,Insert_State ; get current state
Not AL ; flip all bits 0 to FFh, or FFh to 0
Mov Insert_State,AL ; store current result
Mov CX,Max_Cursor ; assume max cursor size
Or AL,AL ; is AL = 0, want min size?
JNZ Tog_1 ; nope, wanted max size
Mov CX,Min_Cursor ; else get min cursor
Tog_1:
Mov AH,1 ; set current scan lines
Mov AL,Curr_V_Mode ; fix AST/AMI 386 Rom BIOS error
Int 10h
Jmp Main ; hop back to main loop
@@:
Cmp AH,4Dh ; is it right arrow
JNE @f ; not a special key so continue
Mov_Right: ; Move cursor right
Mov AL,Curr_Col ; get current column
Cmp AL,Max_Right ; get right border
JB Mov_R ; are we left of right border
Jmp Err_Beep ; nope, so beep
Mov_R:
Inc AL ; move current column right
Mov Curr_Col,AL ; update memory variable
Call Near Ptr Mov_Cursor ; move cursor where desired
Jmp Main
@@:
Cmp AH,4Bh ; is it a left arrow
JNE @f ; not that key so continue
Mov_Left: ; Move cursor left
Mov AL,Curr_Col
Cmp AL,Start_Col ; are we right of left border
JA Mov_L
Jmp Err_Beep ; nope, so beep
Mov_L:
Dec AL
Mov Curr_Col,AL
Call Near Ptr Mov_Cursor ; move cursor where desired
Jmp Main
@@:
Cmp AH,47h ; is it the home key
JNE @f ; not that key so continue
Mov_Home: ; Cursor Home, to start of string
Mov AL,Start_Col ; get starting column
Mov Curr_Col,AL ; make current column = starting
Call Near Ptr Mov_Cursor ; move cursor where desired
Jmp Main ; hop back into main loop
@@:
Cmp AH,53h ; is it Del key
JNE @f ; not that key so continue
Del_Char: ; else, delete current character
Call Near Ptr Mov_Buff_Left ; move string at right of cursor, left
Call Near Ptr Show_String ; but don't move cursor
Jmp Main
@@:
Cmp AH,4Fh ; is it the end key?
JE Mov_End ; yes
Jmp Main ; nope so start again
Mov_End: ; Move to End of buffer
Mov AL,Max_Right
Mov Curr_Col,AL
Call Near Ptr Mov_Cursor ; move cursor where desired
Jmp Main
EVEN
Quit:
Mov AH,1 ; reset cursor to original size
Mov AL,Curr_V_Mode ; fix AST/AMI 386 Rom BIOS error
Mov CX,Orig_Cursor
Int 10h
Mov BP,Old_BP ; restore BP in case bios changed it
Mov BX,EXITKEY ; get address of EXITKEY
Mov AX,Exit_Key ; save ExitKey
Or AL,AL ; make sure return value in AL
JNZ @f
Mov AL,AH ; if not then move to AL
@@:
Xor AH,AH ; and make sure that AH = 0
Mov [BX],AX ; store in EXITKEY
CopyString:
Mov AL,Max_Len ; get length of string in AX
Xor AH,AH ; clear high byte
Mov CX,AX ; put length in CX
Mov DI,OFFSET B$TEMPDATA ; move address of string to DI
Dec AX ; make Max_Len zero biased
Add DI,AX ; get last byte (beginning + length)
Mov AL,20h ; look for trailing spaces
STD ; set direction down, scan backwards
Repz Scasb ; search for non match (ES:DI w/ AL)
CLD ; clear direction flag
JZ Err_Quit ; all spaces so quit
Inc CX ; remove 1 byte overrun of SCASB
; standard way to return a string to QBASIC
Push DS ; Store the Data Segment
Mov AX, OFFSET B$TEMPDATA
Push AX ; Store offset of string
Push CX ; Store LENGTH of string
Push DS ; Store the Data Segment
Mov AX, OFFSET B$STRINGLEN
Push AX ; Store Descriptor of string
Xor AX,AX ; tell Basic it is a variable string
Push AX ; Store a 0
Call B$ASSN ; copy string into BASIC space
Mov AX, OFFSET B$STRINGLEN ; address of descriptor
Ret
EVEN
Err_Quit:
; this returns a null string if have an error
Mov AH,1 ; reset cursor to original size
Mov CX,Orig_Cursor
Mov AL,Curr_V_Mode ; fix AST/AMI 386 Rom BIOS error
Int 10h
Err_Quit1:
Mov BP,Old_BP ; restore BP in case bios changed it
Mov BX,EXITKEY
Xor AX,AX ; return no exit key
Mov [BX],AX
Mov AX, OFFSET B$STRINGLEN ; put address of
Push AX ; descriptor in AX
Call B$STDL ; make it a null string
Mov AX, OFFSET B$STRINGLEN ; put address of descriptor in AX
Ret
EDITOR ENDP
;--------------------------- Jump Section-------------------------
;simple procedures with local labels so that they will not have public names
;and take up space in the .OBJ file with use full PROC directives
EVEN
Mov_Cursor Label Near ; this is a common routine
Mov DH,Curr_Row ; move cursor to that location
Mov DL,Curr_Col ; Row at Curr_Row, Col at Curr_Col
Mov BH,Curr_Page ; this allows use of any video page
Mov AH,2
Int 10h
Retn
EVEN
Show_String Label Near
; turn off cursor until printing is complete
Mov BH,Curr_Page ; get current page in BH
Mov AH,3 ; read cursro info
Int 10h ; Clear cursor by
Or CH,20h ; by turning on bit 5 of CH
Mov AH,1 ; set Cursor size function
Mov AL,Curr_V_Mode ; fix AST/AMI 386 Rom BIOS error
Int 10h ; do it
Mov AH,2 ; move cursor to beginning of string
Mov DH,Start_Row ; note BH contains Curr_Page
Mov DL,Start_Col ; load starting Row & Column
Int 10h
Mov CL,Max_Len ; determine how many bytes to show
Xor CH,CH ; clear CH
Mov SI,OFFSET B$TEMPDATA ; get the offset of buffer into SI
EVEN
Looper1:
Lodsb ; load DS:SI into AL
Mov AH,0Eh ; display AL & move cursor
Int 10h ; (now hidden)
Loop Looper1
Mov AH,3 ; make cursor visable again
Int 10h ; get current cursor
And CH,11011111b ; clear bit 5
Mov AH,1 ; reset cursor so it is now displays
Mov AL,Curr_V_Mode ; fix AST/AMI 386 Rom BIOS error
Int 10h
Jmp Mov_Cursor ; move cursor to desired location
; & return from whence we came
EVEN
Add_Char Label Near
Mov CX,AX ; temporarily store AX in CX
Mov AL,Insert_State ; see if Insert Mode is on
Cmp AL,0 ; i.e. is AL <> 0?
JE Add_Char1 ; nope, AL = 0 insert off, skip ahead
Mov AL,Curr_Col ; get current location
Cmp Max_Right,AL ; are we at right column edge?
JE Add_Char1 ; yes so add to buffer, & ignore Insert mode
Mov_Buff_Right:
; must preserve CX
Mov DX,CX ; store CX in DX to preserve CX
Mov BX,Right_Edge ; load BX w/ right side of buffer
Mov DI,BX ; set destination in ES:DI
Dec BX ; reduce right side by one
Mov SI,BX ; set source in DS:SI
Mov AL,Curr_Col ; find how many words to
Mov CL,Max_Right ; right of cursor
Sub CL,AL
Inc CL ; remove 0 bias
Xor CH,CH ; number of bytes in CX
Std ; use STD to count down
Rep MovSB
Cld ; reset flag
Mov CX,DX ; restore CX to original value
Add_Char1:
Mov SI, OFFSET B$TEMPDATA ; get address of buffer in SI
Mov AL,Start_Col
Mov BL,Curr_Col
Sub BL,AL
Xor BH,BH
Mov DS:[SI+BX],CL
Call Near Ptr Show_String
Mov AL,Curr_Col
Cmp AL,Max_Right
JB Add_Char2
Jmp Main
Add_Char2:
Inc AL ; increment the cursor location
Mov Curr_Col,AL
Call Near Ptr Mov_Cursor ; move cursor where desired
Jmp Main ; start loop again
EVEN
Mov_Buff_Left Label Near
; moves the buffer left to erase a character or characters
Mov BX,OFFSET B$TEMPDATA
Mov AL,Start_Col
Mov CL,Curr_Col
Sub CL,AL
Xor CH,CH
Add BX,CX
Mov DI,BX ; put destination in ES:DI
Inc BX
Mov SI,BX ; put source in DS:SI
Mov CL,Max_Right
Mov AL,Curr_Col
Sub CL,AL
Inc CL ; find how many words to move
Rep MovSB
Mov BX,Right_Edge ; get right side of buffer
Mov AL,ASCII_Space ; put ASCII space in AL
Mov DS:[BX],AL ; add ASCII space to end of string
Retn
END